#include <stdio.h>
#include <modbus.h>
#include <modbus-tcp.h>
#include <string.h>
#include <stdlib.h>
#include "shmem.h"
#include "cJSON.h"
#include "list.h"
#include "msgqueue.h"
#include <pthread.h>
pthread_t t1, t2;
int msgid;
int nodenumber;
int *nodenum;
struct list_head *pos;
struct list_head head;
struct mb_node_list *tmp;
struct mb_node_list *tmp1;
//链表
struct mb_node
{
    int key;        //唯一键值
    char name[128]; //数据点名称
    int type;       //数据点类型
    int addr;
};
struct mb_node_list
{
    struct mb_node node;
    struct list_head list;
};
struct shm_param para;
//数据采集
void *get_info(void *arg)
{
    
    uint16_t data[4] = {};
    uint8_t dest[2] = {};
    
    // struct shm_param para;
    // para=shm_creat();
    // int *nodenum = (int *)shm_getaddr(&para);
    struct std_node *add = (struct std_node *)(nodenum + 1);
    modbus_t *ctx = (modbus_t *)arg;
    while (1)
    {
        list_for_each(pos, &head)
        {
            tmp1 = list_entry(pos, struct mb_node_list, list);
            //光线传感器
            if (tmp1->node.key == 101)
            {
                modbus_read_input_registers(ctx, 1 , 2, data);
            }
            //烟感
            else if (tmp1->node.key == 103)
            {
                modbus_read_input_registers(ctx, 3 , 2, data + 2);
            }
            //灯控开关
            else if (tmp1->node.key == 102)
            {
                modbus_read_bits(ctx, tmp1->node.addr , 2, dest);
            }
            //报警开关
            else if (tmp1->node.key == 104)
            {
                modbus_read_bits(ctx, tmp1->node.addr -1 , 2, dest + 2);
            }
            float lighting = modbus_get_float_dcba(data);
            float light = modbus_get_float_dcba(data + 2);
            //将数据打印
            printf("光线传感器:%.2f　烟感传感器:%.2f\n", lighting, light);
            //printf("光线寄存器:%u  烟感寄存器:%u\n", data[0], data[2]);
            printf("灯开关的状态:%u 报警开关的状态:%u\n", dest[0], dest[1]);
        }
        //插入到共享内存
        for (int i = 0; i < 12; i++)
        {
            //光线传感器
            if (add[i].key == 101)
            {
                add[i].old_val.f_val = add[i].new_val.f_val;
                printf("lighting_old_val:%.2f\n", add[i].old_val.f_val);
                add[i].new_val.f_val = modbus_get_float_dcba(data);
                printf("lighting_new_val:%.2f\n", add[i].new_val.f_val);
                if (add[i].new_val.f_val != 0)
                {
                    add[i].ret = 0;
                }
                else
                {
                    add[i].ret = -1;
                    printf("lighting get err\n");
                }
            }
            //灯控开关
            else if (add[i].key == 102)
            {
                add[i].old_val.b_val = add[i].new_val.b_val;
                printf("linght_switch_old_val:%d\n", add[i].old_val.b_val);
                add[i].new_val.b_val = dest[0];
                printf("light_switch_new_val:%d\n", add[i].new_val.b_val);
                if (add[i].new_val.f_val != 0)
                {
                    add[i].ret = 0;
                }
                else
                {
                    add[i].ret = -1;
                    printf("light get err\n");
                }
            }
            //烟感
            else if (add[i].key == 103)
            {
                add[i].old_val.f_val = add[i].new_val.f_val;
                printf("smoke_old_val:%.2f\n", add[i].old_val.f_val);
                add[i].new_val.f_val = modbus_get_float_dcba(data + 2);
                printf("smoke_new_val:%.2f\n", add[i].new_val.f_val);
                if (add[i].new_val.f_val != 0)
                {
                    add[i].ret = 0;
                }
                else
                {
                    add[i].ret = -1;
                    printf("smoke get err\n");
                }
            }
            //报警开关
            else if (add[i].key == 104)
            {
                add[i].old_val.b_val = add[i].new_val.b_val;
                printf("alram_switch_old_val:%d\n", add[i].old_val.b_val);
                add[i].new_val.b_val = dest[1];
                printf("alram_switch_new_val:%d\n", add[i].new_val.b_val);
                if (add[i].new_val.f_val != 0)
                {
                    add[i].ret = 0;
                }
                else
                {
                    add[i].ret = -1;
                    printf("alarm get err\n");
                }
            }
        }
        sleep(1);
    }
    //shm_del(&para);
    pthread_exit(NULL);
}
//指令控制
void *set_op(void *arg)
{
    modbus_t *ctx = (modbus_t *)arg;
    struct msgbuf msb;
    msb.type = 2;
    while (1)
    {
        if (msgrcv(msgid, &msb, sizeof(msb) - sizeof(long), 2, 0) > 0)
        {
            //遍历链表
            int val=atoi(msb.val);
            list_for_each(pos, &head)
            {
                tmp = list_entry(pos, struct mb_node_list, list);
                if (msb.key == tmp->node.key)
                {
                    if (msb.key == 102) //灯控是线圈寄存器
                    {
                        modbus_write_bit(ctx, tmp->node.addr , val);
                    }
                    else if (msb.key == 104) //报警线圈寄存器
                    {
                        modbus_write_bit(ctx, tmp->node.addr, val);
                    }
                }
            }
            printf("\n");
        }
        else
        {
            perror("recv error:");
        }
        printf("%d\n",msgid);
    }
    pthread_exit(NULL);
    //pause();
}
int main(int argc, char const *argv[])
{
    para=shm_creat(&nodenumber);
    nodenum = (int *)shm_getaddr(&para);
    msgid=msgqueue_create();
    printf("%d\n",msgid);
    
    //初始化链表
    INIT_LIST_HEAD(&head);
    //打开文件
    FILE *fd = fopen("/home/hq/24011/project/datapot.json", "r+");
    if (fd == NULL)
    {
        printf("fopen err\n");
    }
    //定位操作
    fseek(fd, 0, SEEK_END);
    //获取当前位置
    int len = ftell(fd);
    fseek(fd, 0, SEEK_SET);
    char *p = (char *)malloc(len + 1);
    fread(p, 1, len, fd);
    cJSON *root = NULL;
    root = cJSON_Parse(p);
    if (NULL == root)
    {
        printf("error\n");
    }
    //解析json的数据
    //解析version
    char *ver = cJSON_GetObjectItem(root, "version")->valuestring;
    printf("version=%s\n", ver);

    //解析mb_dev
    cJSON *DEV = cJSON_GetObjectItem(root, "mb_dev");          //解析对象
    char *ADD = cJSON_GetObjectItem(DEV, "addr")->valuestring; //解析对象中的字符串
    int por = cJSON_GetObjectItem(DEV, "port")->valueint;      //解析对象中的整型数字
    printf("ip=%s port=%d\n", ADD, por);

    //解析modbus并插入链表
    cJSON *MOD = cJSON_GetObjectItem(root, "modbus");
    cJSON *DATA = cJSON_GetObjectItem(MOD, "data"); //解析数组
    int DA_size = cJSON_GetArraySize(DATA);
    cJSON *DA_item = DATA->child; //获取子对象

    for (int i = 0; i < DA_size; i++)
    {
        struct mb_node_list *arr = (struct mb_node_list *)malloc(sizeof(struct mb_node_list));
        printf("key:%d\n", cJSON_GetObjectItem(DA_item, "key")->valueint);
        printf("name:%s\n", cJSON_GetObjectItem(DA_item, "name")->valuestring);
        printf("addr:%d\n", cJSON_GetObjectItem(DA_item, "addr")->valueint);
        printf("type:%d\n", cJSON_GetObjectItem(DA_item, "type")->valueint);

        arr->node.key = cJSON_GetObjectItem(DA_item, "key")->valueint;
        arr->node.type = cJSON_GetObjectItem(DA_item, "type")->valueint;
        arr->node.addr=cJSON_GetObjectItem(DA_item,"addr")->valueint;
        list_add(&arr->list, &head);
        DA_item = DA_item->next;
    }
    //创建modbus实例
    modbus_t *ctx = modbus_new_tcp(ADD, por);
    if (ctx == NULL)
    {
        perror("modbus err");
        return -1;
    }
    //设置从机id
    modbus_set_slave(ctx, 1);
    //建立链接,
    if (modbus_connect(ctx) < 0)
    {
        perror("modbus connect err");
        return -1;
    }
    //创建数据采集的线程
    if (pthread_create(&t1, NULL, get_info, ctx) != 0)
    {
        perror("get_info thread create err");
        return -1;
    }
    //创建指令处理的线程
    if (pthread_create(&t2, NULL, set_op, ctx) != 0)
    {
        perror("set_op thread create err");
        return -1;
    }
    // struct msgbuf m1;
    // m1.type=2;
    // m1.key=102;
    // char a[]="0";
    // strcpy(m1.val,a);
    // msgsnd(msgid, &m1, sizeof(m1)-sizeof(long), 0); 
    //线程回收
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    //关闭套接字
    modbus_close(ctx);
    //释放空间
    modbus_free(ctx);
    return 0;
}